1
|
|
|
/** global: UB */ |
2
|
|
|
|
3
|
|
|
/*! ARRAY UTILS */ |
4
|
|
|
|
5
|
|
|
var arrayFuncs = { |
6
|
|
|
|
7
|
|
|
unique: function(output = null){ |
8
|
|
|
var list = this; |
9
|
|
|
return list.deleteDuplicates(output); |
10
|
|
|
}, |
11
|
|
|
deleteDuplicates: function(output = null){ |
12
|
|
|
var list = this; |
13
|
|
|
|
14
|
|
|
if (output == null) { |
15
|
|
|
output = []; |
16
|
|
|
} |
17
|
|
|
|
18
|
|
|
var o = output.length; |
19
|
|
|
|
20
|
|
|
for (var i = 0, il = list.length;i<il;i++){ |
21
|
|
|
var item = list[i]; |
22
|
|
|
|
23
|
|
|
if(item != null){ |
24
|
|
|
if(output.indexOf(item) === -1) { |
25
|
|
|
output[o++] = item; |
26
|
|
|
} |
27
|
|
|
} |
28
|
|
|
} |
29
|
|
|
return output; |
30
|
|
|
}, |
31
|
|
|
|
32
|
|
|
/** Generate a 2D array of all possible combinations, given a 1D array of any values. |
33
|
|
|
|
34
|
|
|
eg : INPUT : [A, B, C] |
35
|
|
|
eg : OUTPUT : [ [A], [B], [A,B], [C], [A,C], [B,C], [A,B,C] ] */ |
36
|
|
|
combinations: function(list){ |
37
|
|
|
var list = this; |
38
|
|
|
var result = []; |
39
|
|
|
var listSize = list.length; |
40
|
|
|
var combinationsCount = (1 << listSize); |
41
|
|
|
|
42
|
|
|
for (var i = 1;i<combinationsCount;i++){ |
43
|
|
|
var combination = []; |
44
|
|
|
for (var j = 0;j<listSize;j++){ |
45
|
|
|
if ((i & (1 << j))){ |
|
|
|
|
46
|
|
|
combination.push(list[j]); |
47
|
|
|
} |
48
|
|
|
} |
49
|
|
|
result.push(combination); |
50
|
|
|
} |
51
|
|
|
return result; |
52
|
|
|
}, |
53
|
|
|
|
54
|
|
|
mostFrequent: function(returnAnyValIfAllFreqSame = true, fallback = 0){ |
55
|
|
|
var list = this; |
56
|
|
|
|
57
|
|
|
// exit quickly if empty |
58
|
|
|
if (!list.Exists()) { |
59
|
|
|
return 0; |
60
|
|
|
} |
61
|
|
|
if (list.length === 1) { |
62
|
|
|
return list[0]; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
|
66
|
|
|
// calc number of occurences |
67
|
|
|
var unique = list.unique(); |
68
|
|
|
var counts = UB.newArray(0, list.length); |
69
|
|
|
var maxCount = 0; |
70
|
|
|
var maxIndex = 0; |
71
|
|
|
for (var i = 0, il = list.length;i<il;i++){ |
72
|
|
|
var val = list[i]; |
73
|
|
|
if (val != null) { |
74
|
|
|
|
75
|
|
|
// find val and count it |
76
|
|
|
var index = unique.indexOf(val); |
77
|
|
|
counts[index]++; |
78
|
|
|
|
79
|
|
|
// find highest frequency |
80
|
|
|
var curCount = counts[index]; |
81
|
|
|
if (maxCount < curCount) { |
82
|
|
|
maxCount = curCount; |
83
|
|
|
maxIndex = index; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
// if all frequencies same (max frequency was 1) .. and custom val wanted back |
90
|
|
|
if (!returnAnyValIfAllFreqSame && maxCount == 1) { |
91
|
|
|
return fallback; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
// return the most frequent item |
95
|
|
|
return unique[maxIndex]; |
96
|
|
|
}, |
97
|
|
|
leastFrequent: function(returnAnyValIfAllFreqSame = true, fallback = 0){ |
98
|
|
|
var list = this; |
99
|
|
|
|
100
|
|
|
// exit quickly if empty |
101
|
|
|
if (!list.Exists()) { |
102
|
|
|
return 0; |
103
|
|
|
} |
104
|
|
|
if (list.length === 1) { |
105
|
|
|
return list[0]; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
// calc number of occurences |
109
|
|
|
var unique = list.unique(); |
110
|
|
|
var counts = UB.newArray(0, list.length); |
111
|
|
|
var maxCount = 0; |
112
|
|
|
for (var i = 0, il = list.length;i<il;i++){ |
113
|
|
|
var val = list[i]; |
114
|
|
|
if (val != null) { |
115
|
|
|
|
116
|
|
|
// find val and count it |
117
|
|
|
var index = unique.indexOf(val); |
118
|
|
|
counts[index]++; |
119
|
|
|
|
120
|
|
|
// find highest frequency |
121
|
|
|
var curCount = counts[index]; |
122
|
|
|
if (maxCount < curCount) { |
123
|
|
|
maxCount = curCount; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
} |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
// if all frequencies same (max frequency was 1) .. and custom val wanted back |
130
|
|
|
if (!returnAnyValIfAllFreqSame && maxCount == 1) { |
131
|
|
|
return fallback; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
// return the most frequent item |
135
|
|
|
return unique[counts.indexOfMin()]; |
136
|
|
|
}, |
137
|
|
|
|
138
|
|
|
total: function(start=0, end=-1) { |
139
|
|
|
var vals = this; |
140
|
|
|
|
141
|
|
|
// exit quickly if few items .. and checking full array |
142
|
|
|
var len = vals.length; |
143
|
|
|
if (end === -1) { |
144
|
|
|
end = len - 1; |
145
|
|
|
} |
146
|
|
|
if (len === 0 || start > end) { |
147
|
|
|
return 0; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
// slowly check all values |
151
|
|
|
if (vals.length === 0) { |
152
|
|
|
return 0; |
153
|
|
|
} |
154
|
|
|
var sum = 0; |
155
|
|
|
for (var i = start; i <= end; i++) { |
156
|
|
|
|
157
|
|
|
// skip nulls |
158
|
|
|
var val = vals[i]; |
159
|
|
|
if (val != null){ |
160
|
|
|
var num = val; |
161
|
|
|
sum += num; |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
return sum; |
165
|
|
|
}, |
166
|
|
|
|
167
|
|
View Code Duplication |
max: function(start=0, end=-1) { |
|
|
|
|
168
|
|
|
var vals = this; |
169
|
|
|
|
170
|
|
|
// exit quickly if few items .. and checking full array |
171
|
|
|
var len = vals.length; |
172
|
|
|
if (end === -1) { |
173
|
|
|
end = len - 1; |
174
|
|
|
} |
175
|
|
|
if (len === 0 || start > end) { |
176
|
|
|
return 0; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
// check all values |
180
|
|
|
var big = Number.NEGATIVE_INFINITY; |
181
|
|
|
var found = 0; |
182
|
|
|
for (var i = start; i <= end; i++) { |
183
|
|
|
|
184
|
|
|
// skip nulls |
185
|
|
|
var val = vals[i]; |
186
|
|
|
if (val != null) { |
187
|
|
|
found++; |
188
|
|
|
var num = val; |
189
|
|
|
if (num > big) { |
190
|
|
|
big = num; |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
// exit if no non-null values found |
196
|
|
|
if (found === 0) { |
197
|
|
|
return 0; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
// return calculated max value |
201
|
|
|
return big; |
202
|
|
|
}, |
203
|
|
|
|
204
|
|
View Code Duplication |
indexOfMax: function(start=0, end=-1) { |
|
|
|
|
205
|
|
|
var vals = this; |
206
|
|
|
|
207
|
|
|
// exit quickly if few items .. and checking full array |
208
|
|
|
var len = vals.length; |
209
|
|
|
if (end === -1) { |
210
|
|
|
end = len - 1; |
211
|
|
|
} |
212
|
|
|
if (len === 0 || start > end) { |
213
|
|
|
return -1; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
// check all values |
217
|
|
|
var big = Number.NEGATIVE_INFINITY; |
218
|
|
|
var slot = -1; |
219
|
|
|
var found = 0; |
220
|
|
|
for (var i = start; i <= end; i++) { |
221
|
|
|
|
222
|
|
|
// skip nulls |
223
|
|
|
var val = vals[i]; |
224
|
|
|
if (val != null) { |
225
|
|
|
found++; |
226
|
|
|
var num = val; |
227
|
|
|
if (num > big) { |
228
|
|
|
big = num; |
229
|
|
|
slot = i; |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
// exit if no non-null values found |
235
|
|
|
if (found === 0) { |
236
|
|
|
return -1; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
// return calculated max value |
240
|
|
|
return slot; |
241
|
|
|
}, |
242
|
|
|
|
243
|
|
View Code Duplication |
min: function(start=0, end=-1) { |
|
|
|
|
244
|
|
|
var vals = this; |
245
|
|
|
|
246
|
|
|
// exit quickly if few items .. and checking full array |
247
|
|
|
var len = vals.length; |
248
|
|
|
if (end === -1) { |
249
|
|
|
end = len - 1; |
250
|
|
|
} |
251
|
|
|
if (len === 0 || start > end) { |
252
|
|
|
return 0; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
// check all values |
256
|
|
|
var small = Number.POSITIVE_INFINITY; |
257
|
|
|
var found = 0; |
258
|
|
|
for (var i = start; i <= end; i++) { |
259
|
|
|
|
260
|
|
|
// skip nulls |
261
|
|
|
var val = vals[i]; |
262
|
|
|
if (val != null){ |
263
|
|
|
found++; |
264
|
|
|
var num = val; |
265
|
|
|
if (num < small) { |
266
|
|
|
small = num; |
267
|
|
|
} |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
// exit if no non-null values found |
273
|
|
|
if (found === 0) { |
274
|
|
|
return 0; |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
// return calculated min value |
278
|
|
|
return small; |
279
|
|
|
}, |
280
|
|
|
|
281
|
|
View Code Duplication |
indexOfMin: function(start=0, end=-1) { |
|
|
|
|
282
|
|
|
var vals = this; |
283
|
|
|
|
284
|
|
|
// exit quickly if few items .. and checking full array |
285
|
|
|
var len = vals.length; |
286
|
|
|
if (end === -1) { |
287
|
|
|
end = len - 1; |
288
|
|
|
} |
289
|
|
|
if (len === 0 || start > end) { |
290
|
|
|
return -1; |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
// check all values |
294
|
|
|
var small = Number.POSITIVE_INFINITY; |
295
|
|
|
var slot = -1; |
296
|
|
|
var found = 0; |
297
|
|
|
for (var i = start; i <= end; i++) { |
298
|
|
|
|
299
|
|
|
// skip nulls |
300
|
|
|
var val = vals[i]; |
301
|
|
|
if (val != null){ |
302
|
|
|
found++; |
303
|
|
|
var num = val; |
304
|
|
|
if (num < small) { |
305
|
|
|
small = num; |
306
|
|
|
slot = i; |
307
|
|
|
} |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
// exit if no non-null values found |
313
|
|
|
if (found === 0) { |
314
|
|
|
return -1; |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
// return calculated min value |
318
|
|
|
return slot; |
319
|
|
|
}, |
320
|
|
|
|
321
|
|
|
avg: function(start=0, end=-1) { |
322
|
|
|
var vals = this; |
323
|
|
|
|
324
|
|
|
// exit quickly if few items .. and checking full array |
325
|
|
|
var len = vals.length; |
326
|
|
|
if (end === -1) { |
327
|
|
|
end = len - 1; |
328
|
|
|
} |
329
|
|
|
if (len === 0 || start > end) { |
330
|
|
|
return 0; |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
// slowly check all values |
334
|
|
|
return vals.total(start, end) / ((end - start)+1); |
335
|
|
|
}, |
336
|
|
|
|
337
|
|
View Code Duplication |
nearest: function(value, start=0, end=-1) { |
|
|
|
|
338
|
|
|
var arr = this; |
339
|
|
|
|
340
|
|
|
// quickly exit if few values |
341
|
|
|
if (arr.length === 0) { |
342
|
|
|
return value; |
343
|
|
|
} |
344
|
|
|
if (arr.length === 1) { |
345
|
|
|
return arr[0]; |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
// returns the nearest value |
349
|
|
|
var dists = []; |
350
|
|
|
if (end === -1) { |
351
|
|
|
end = arr.length - 1; |
352
|
|
|
} |
353
|
|
|
for (var a = start; a <= end; a++) { |
354
|
|
|
dists.push(arr[a].distance(value)); |
355
|
|
|
} |
356
|
|
|
var index = dists.indexOfMin(); |
357
|
|
|
return arr[start + index]; |
358
|
|
|
}, |
359
|
|
|
|
360
|
|
View Code Duplication |
indexOfNearest: function(value, start=0, end=-1) { |
|
|
|
|
361
|
|
|
var arr = this; |
362
|
|
|
|
363
|
|
|
// quickly exit if few values |
364
|
|
|
if (arr.length === 0) { |
365
|
|
|
return -1; |
366
|
|
|
} |
367
|
|
|
if (arr.length === 1) { |
368
|
|
|
return 0; |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
// returns the index of the nearest value |
372
|
|
|
var dists = []; |
373
|
|
|
if (end === -1) { |
374
|
|
|
end = arr.length - 1; |
375
|
|
|
} |
376
|
|
|
for (var a = start; a <= end; a++) { |
377
|
|
|
dists.push(arr[a].distance(value)); |
378
|
|
|
} |
379
|
|
|
var index = dists.indexOfMin(); |
380
|
|
|
return (start + index); |
381
|
|
|
}, |
382
|
|
|
|
383
|
|
|
height: function(start=0, end=-1) { |
384
|
|
|
var arr = this; |
385
|
|
|
return arr.max(start, end) - arr.min(start, end); |
386
|
|
|
}, |
387
|
|
|
|
388
|
|
|
none:null |
389
|
|
|
}; |
390
|
|
|
|
391
|
|
|
// register funcs |
392
|
|
|
UB.registerFuncs(Array.prototype, arrayFuncs); |
393
|
|
|
|